﻿#region License, Terms and Conditions
//
// Copyright (c) 2008, aspZone.com
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY aspZone.com ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author(s):
//  John Rudolf Lewis (http://aspZone.com)
//
#endregion

namespace AspZone.Commerce.Service
{
    using System.Collections.Generic;
    using System.Linq;
    using AspZone.Commerce.Model;
    using AspZone.Commerce.Repositories;

    public class CatalogService : AspZone.Commerce.Service.ICatalogService
    {
        private ICategoryRepository categoryRepository;
        private IProductRepository productRepository;

        public CatalogService(ICategoryRepository categoryRepository, IProductRepository productRepository)
        {
            this.categoryRepository = categoryRepository;
            this.productRepository = productRepository;
        }

        public IList<Category> GetCategoryHierarchy()
        {
            this.categoryRepository.IncludeProducts = false;
            
            var categories = this.categoryRepository
                .Categories
                .ToHierarchicalList();

            return categories;
        }

        public Category GetCategoryBySEOName(string seoName)
        {
            this.categoryRepository.IncludeProducts = true;
            var category = this.categoryRepository.Categories.WhereSEONameEquals(seoName);
            return category;
        }

        public Product GetProductBySEOName(string seoName)
        {
            this.productRepository.IncludeCategories = false;
            var product = this.productRepository.Products.WhereSEONameEquals(seoName);
            return product;
        }

        public IList<Product> GetProductsByCategory(string seoName)
        {
            // Get a list of all categoryIds, started with the category specified by the seoName parameter,
            // followed by all its children, recursively.
            var categoryIds = new List<int>();
            var stack = new Stack<Category>();
            // push the Id of the specified category onto the stack
            stack.Push(this.categoryRepository.Categories.WhereSEONameEquals(seoName));
            while (stack.Count > 0)
            {
                // pop the stack
                var category = stack.Pop();
                // add the Id to the lsit
                categoryIds.Add(category.Id);
                // get all the child categories
                var childCategories = this.categoryRepository.Categories.WhereParentCategoryIdEquals(category.Id);
                // push them onto the stack
                foreach (var childCategory in childCategories)
                {
                    stack.Push(childCategory);
                }
            }
            this.productRepository.IncludeCategories = true;
            var products = this.productRepository
                .Products
                .ThatAreInCategory(categoryIds)
                .ToList();

            return products;

        }


    }
}
